/* Copyright Paul Reiche, Fred Ford. 1992-2002, Christopher Night 2013

This file is part of the HTML5 port of Ur-Quan Masters (UQM-HTML5)

UQM-HTML5 is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

UQM-HTML5 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Public License for more details.

You should have received a copy of the GNU General Public License along with this program.  If not,
see <http://www.gnu.org/licenses/>. */


var weapon = {

	weapon_collision: function (target) {
		var damage = this.mass
		if (damage && (target.state.FINITE_LIFE || target.life_span == 1)) {
			// TODO?: lasers from same ship can't hit each other
			misc.do_damage(target, damage)
			if (target.hit_points) this.state.COLLISION = true
		}
		if (!target.state.FINITE_LIFE || (!target.state.COLLISION && this.hit_points <= target.mass)) {
			// TODO: sound effect
			// TODO: this is a temporary hack for lasers
			if (!this.origin) this.state.DISAPPEARING = true
			this.hit_points = 0
			this.life_span = 0
			this.state.COLLISION = this.state.NONSOLID = true
			elements.push(new Blast(this))
		}
	},

	// apply this to something that's supposed to turn to face enemy ships
	TrackShip: function () {
		var closest = 1e20, direction = 0, target = null
		for (var j = 0 ; j < elements.length ; ++j) {
			var element = elements[j]
			if (!element.state.PLAYER_SHIP) continue
			if (element.playerNr == this.playerNr) continue
			// For some reason, trackers that are APPEARING can track cloaked ships
			if (element.state.CLOAKED && !(this.state.PLAYER_SHIP && this.state.APPEARING)) continue
			if (!(element.life_span && element.crew_level)) continue
			if (element.state.PRE_PROCESS) {
				var dx = element.next.x - this.next.x, dy = element.next.y - this.next.y
			} else {
				var dx = element.current.x - this.current.x, dy = element.current.y - this.current.y
			}
			dx = zmod(dx, ARENA_WIDTH)
			dy = zmod(dy, ARENA_HEIGHT)
			var d2 = dx * dx + dy * dy
			if (d2 < closest) {
				closest = d2 ; target = element ; direction = Math.atan2(dx, dy)
			}
		}
		if (!target) return null
		var dA = zmod(direction / tau * 16 - this.facing, 16)
		if (Math.abs(dA) > 0.5) {
			this.facing = rmod(this.facing + (dA > 1 ? 1 : -1), 16)
		}
		return target
	},
	
}



function Missile(info, sender) {
	//console.log("Missile on", battleFrameCount)
	this.info = info
	this.parent = sender
	this.playerNr = sender.playerNr
	this.state = {
		APPEARING: true,
		FINITE_LIFE: true,
	}
	if (info.flags) {
		for (var flag in info.flags) this.state[flag] = info.flags[flag]
	}
	this.life_span = info.life
	this.hit_points = info.hit_points
	this.mass = info.damage
	this.frames = info.frames
	this.facing = this.parent.facing
	var A = this.facing * tau / 16
	this.current = {
		x: sender.current.x + info.pixoffs * Math.sin(A),
		y: sender.current.y + info.pixoffs * Math.cos(A),
		frame: this.frames[this.facing],
	}
	this.vx = info.speed * Math.sin(A) * 0.25
	this.vy = info.speed * Math.cos(A) * 0.25
}
Missile.prototype = {
	preprocess_func: function () {
		if (this.info.preprocess_func) this.info.preprocess_func.apply(this)
	},
	collision_func: weapon.weapon_collision,
}


function Laser(info, sender) {
	this.info = info
	this.parent = sender
	this.playerNr = sender.playerNr
	this.hit_points = info.hit_points || 1
	this.mass = info.mass || 1
	// 
	this.life_span = 2
	this.state = {
		APPEARING: true,
		FINITE_LIFE: true,
		// Collision detection override - always connect with anything in your path, even if
		// moving apart.
		ALWAYS_APPROACHING: true,
		SKIP_DRAW: true,
	}
	if (info.flags) {
		for (var flag in info.flags) this.state[flag] = info.flags[flag]
	}
	var A = (info.face || 0) * tau / 16
	this.frames = [graphics.get1x1()]
	this.current = {
		x: sender.next.x + info.pixoffs * Math.sin(A),
		y: sender.next.y + info.pixoffs * Math.cos(A),
		frame: this.frames[0],
	}
	this.origin = {
		x: this.current.x,
		y: this.current.y,
	}
	this.color = info.color
	if (info.target) {
		this.next = {
			x: info.target.next.x,
			y: info.target.next.y,
			frame: this.frames[0],
		}
	} else {
		// TODO: fire straight ahead
	}
	this.facing = rmod(Math.round(Math.atan2(this.vx, this.vy) * tau / 16), 16)
	//console.log("laser gearing up", battleFrameCount, this.origin, this.current, this.next)
}
Laser.prototype = {
	// Because lasers are created after collision detection happens and only last one frame,
	// we want them to finish off the frame they're created, and appear on the following frame.
	// The original did this by having a separate element that created the laser at the end of its
	// life. We use the SKIP_DRAW flag to not draw until preprocessing has run once.
	preprocess_func: function () {
		this.state.SKIP_DRAW = false
		this.current.x = this.origin.x = this.parent.next.x
		this.current.y = this.origin.y = this.parent.next.y
		this.next.x = this.info.target.next.x
		this.next.y = this.info.target.next.y
		this.current.px = Math.round(this.current.x)
		this.current.py = Math.round(this.current.y)
		this.next.px = Math.round(this.next.x)
		this.next.py = Math.round(this.next.y)
		//console.log("laser preprocess", battleFrameCount, this.current, this.next, this.state.APPEARING)
	},
	collision_func: function (element) {
		if (this.state.APPEARING) return
		//console.log("laser colliding", element, element.current, element.next)
		this.vx = this.next.x - this.current.x
		this.vy = this.next.y - this.current.y
		weapon.weapon_collision.call(this, element)
	},
}

function Blast(weap) {
	this.playerNr = weap.playerNr
	this.state = {
		APPEARING: true,
		FINITE_LIFE: true,
		NONSOLID: true,
		SKIP_COLLISION: true,
	}
	var blast_offs = weap.info.blast_offs || 0
	var A = Math.atan2(weap.vx, weap.vy)
	this.current = {
		x: weap.next.x + blast_offs * Math.sin(A),
		y: weap.next.y + blast_offs * Math.cos(A),
	}
	this.next = {}
	// Apparently some weapons' frame arrays contain the animation for the blast when they hit.
	var num_blast_frames = weap.frames.length - 16
	if (num_blast_frames <= 0) {
		// The default non-animated blast
		this.index = rmod(Math.round(A * tau / 8), 8)
		this.life_span = 2
		this.farray = graphics.getfarray("lbm/blabig.ani")
		this.current.frame = this.farray[this.index]
	} else {
		this.frame_index = 16
		this.life_span = num_blast_frames - 1
		this.farray = weap.frames
		this.current.frame = this.farray[this.frame_index]
		this.preprocess_func = ship.animation_preprocess
	}
}


